package cn.edu.zju.om.crawler;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.EntityStore;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.StoreConfig;

public class TaskManager {
	
	private PrimaryIndex<String, Task> tasks;
	
	private Environment dBEnvironment;
	
	private EntityStore store;
	
	private static TaskManager instance = null;
	
	private Queue<Task> taskQueue;
	
	private boolean closed = false;
	
	private TaskManager() {
		// Instantiate an environment configuration object
		EnvironmentConfig myEnvConfig = new EnvironmentConfig();

		// If the environment is opened for write, then we want to be
		// able to create the environment if it does not exist.
		myEnvConfig.setAllowCreate(true);
		// Instantiate the Environment. This opens it and also possibly
		// creates it.
		File dbDic = new File("taskDB");
		if (!dbDic.exists()) {
			dbDic.mkdir();
		}

		dBEnvironment = new Environment(dbDic, myEnvConfig);
		
		StoreConfig storeConfig = new StoreConfig();
		storeConfig.setAllowCreate(true);
		store = new EntityStore(dBEnvironment, "TaskStore", storeConfig);
		
		tasks = store.getPrimaryIndex(String.class, Task.class);
		
		taskQueue = new ConcurrentLinkedQueue<Task>();
		
		restoreTaskQueue();
	}

	private void restoreTaskQueue() {
		EntityCursor<Task> taskCursor = tasks.entities();
		
		for(Task task : taskCursor) {
			if(!task.isDone()) {
				taskQueue.add(task);
			}
		}
		
		taskCursor.close();
	}
	
	public static TaskManager getInstance() {
		if (instance == null) {
			instance = new TaskManager();
		}
		
		return instance;
	}
	
	public void addTask(String url) {
		if (tasks.contains(url)) {
			return;
		}
		
		Task task = new Task(url);
		
		tasks.put(task);
		taskQueue.add(task);
	}
	
	public boolean hasTask() {
		if (taskQueue.isEmpty()) {
			return false;
		}
		
		return true;
	}
	
	public Task getTask() {
		return taskQueue.poll();
	}
	
	public void updateTask(Task task) {
		tasks.put(task);
	}
	
	public List<Task> getFailedTasks() {
		List<Task> failedTasks = new ArrayList<Task>();
		
		return failedTasks;
	}
	
	public void close() {
		store.close();
		dBEnvironment.cleanLog();
		dBEnvironment.close();
		closed = true;
	}

}
